module sCPU(
    input clk,
    input reset,
    input [7:0] ins,
    output reg [3:0] pc,
    output reg [7:0] out_rs
);
// 默认`? :`可以综合成Mux
// 指令拆解
wire [1:0] op, rd, rs1, rs2, rs1_m;
wire [3:0] jump_pc, imm;
assign {op, rd, rs1, rs2} = ins;
assign jump_pc = ins[5:2];
assign imm = ins[3:0];
assign rs1_m = (op==2'd3)? 2'b0: rs1; // bner0和R[0]比较

// 寄存器堆
wire [7:0] data, r1, r2;
wire w_en;
assign w_en = op[0]==0; //写使能
assign data = op[1]? {4'b0, imm} : r1 + r2; //等待写的数据
Register #(8, 4) R(
    .clk(clk),
    .reset(reset),
    .w_en(w_en),
    .addr(rd),
    .data(data),
    .addr1(rs1_m),
    .addr2(rs2),
    .r1(r1),
    .r2(r2)
);
// PC
always @(posedge clk) begin
    if (reset) begin
        pc <= '0;
    end else begin
        pc <= ((op==2'd3) & (r1!=r2))? jump_pc: pc+1'b1;
        // $display("exe %x", ins);
        out_rs <= (op==2'd1)? r1: out_rs;
    end
end

endmodule

module Register #(WIDTH=8, NUM=4) (
    input clk,
    input reset,
    input w_en,
    input [1:0] addr,
    input [1:0] addr1,
    input [1:0] addr2,
    input [7:0] data,
    output [7:0] r1,
    output [7:0] r2
);
reg[(WIDTH-1):0] R[NUM];
assign r1 = R[addr1];
assign r2 = R[addr2];

integer i;
always @(posedge clk) begin
    if(reset) begin
        for(i=0; i< NUM; i = i+1) begin
            R[i] <= 0;
        end
    end else begin
        // 希望能综合成带使能的D-FlipFlop
        R[addr] <= w_en? data: R[addr];
    end
end
endmodule
